package com.example.wanjinyou.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.wanjinyou.mapper.ArticleBodyMapper;
import com.example.wanjinyou.mapper.ArticleMapper;
import com.example.wanjinyou.mapper.CategoryMapper;
import com.example.wanjinyou.pojo.entity.Article;
import com.example.wanjinyou.pojo.entity.ArticleBody;
import com.example.wanjinyou.pojo.entity.Category;
import com.example.wanjinyou.pojo.entity.User;
import com.example.wanjinyou.service.ArticleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.wanjinyou.service.CategoryService;
import com.example.wanjinyou.service.ThreadService;
import com.example.wanjinyou.service.UserService;
import com.example.wanjinyou.vo.ArticleBodyVo;
import com.example.wanjinyou.vo.ArticleVo;
import com.example.wanjinyou.vo.CategoryVo;
import com.example.wanjinyou.vo.Result;
import com.example.wanjinyou.vo.params.PageParams;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Mr.Chen
 * @since 2022-10-20
 */
@Service
public class ArticleServiceImpl  implements ArticleService {

    @Autowired
    private ArticleMapper articleMapper;
    @Autowired
    private UserService userService;
    @Autowired
    private ArticleBodyMapper articleBodyMapper;
    @Autowired
    private CategoryService categoryService;
    /**
     * 首页文章列表
     * @param pageParams
     * @return
     */
    @Override
    public Result listArticle(PageParams pageParams) {
        //分页查询article数据库表
        Page<Article> page = new Page<>(pageParams.getPage() , pageParams.getPageSize());
        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
        //构造查询语句
        //根据是否置顶排序
        queryWrapper.orderByDesc(Article::getWeight);
        //order by create_data 根据创建时间进行排序
        queryWrapper.orderByDesc(Article::getCreateData);
        //根据查询语句进行分页查询
        IPage<Article> articleIPage = articleMapper.selectPage(page, queryWrapper);
        List<Article> records = articleIPage.getRecords();  //查询结果放到List中

        //转换成VO对象
        List<ArticleVo> articleVolist = copyList(records,true);
        //返回给前端
        return Result.success(articleVolist);
    }

    /**
     * 查找最热文章
     * @param
     * @return
     */
    @Override
    public Result hotArticle(int limit) {
        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
        //slect id,title from article order by view_counts desc limit 5;
        queryWrapper.orderByDesc(Article::getViewCounts); //根据文章浏览量进行倒序排列
        queryWrapper.select(Article::getId,Article::getTitle);
        queryWrapper.last("limit " + limit);

        List<Article> articles = articleMapper.selectList(queryWrapper); //查询
        return Result.success( copyList(articles,false) );  //转化为vo对象返回
    }

    /**
     * 查看文章详情
     * @param articleId
     * @return
     */
    @Autowired
    ThreadService threadService;

    @Override
    public Result findArtileBodyById(Long articleId) {
        //1.根据文章id查找文章信息
        Article article = articleMapper.selectById(articleId);
        ArticleVo articleVo =  copy(article,true,true,true);
        //2.查看完文章之后,要更新浏览量量, 更新耗时会增加此次接口的耗时, 如果一旦更新出问题不能影响查看文章的操作
        // 此处可以用一个线程池来完成 将更新阅读数的操作放到线程池中执行,不影响主线程的操作
        threadService.updateViewCount(articleMapper,article);

        return Result.success(articleVo);


    }

    //进行批量转换
    private List<ArticleVo> copyList(List<Article> records,boolean isAuthor) {
        List<ArticleVo> articleVoList = new ArrayList<>();
        for( Article record : records) {
            articleVoList.add( copy(record,isAuthor,false,false) );
        }
        return articleVoList;
    }

    //进行批量转换
    private List<ArticleVo> copyList(List<Article> records,boolean isAuthor,boolean isBody, boolean isCategory) {
        List<ArticleVo> articleVoList = new ArrayList<>();
        for( Article record : records) {
            articleVoList.add( copy(record,isAuthor,isBody,isCategory) );
        }
        return articleVoList;
    }

    //转换单个vo对象
    private ArticleVo copy(Article article,Boolean isAuthor,boolean isBody, boolean isCategory) {
        ArticleVo articleVo = new ArticleVo();
        BeanUtils.copyProperties(article,articleVo);
        //为true设置作者的信息
        if( isAuthor) {
            //
            User user = userService.findUserById( articleVo.getAuthorId() ); //根据作者id查找作者
            articleVo.setAuthorNickName( user.getNickName()); //将昵称设置给返回的articlevo中
        }
        //为true设置文章详情信息
        if( isBody) {
            Integer bodyId = article.getBodyId();
            //根据文章的bodyId找到文章内容
            ArticleBody articleBody = articleBodyMapper.selectById(bodyId);
            //转换为ArticleVo
            ArticleBodyVo articleBodyVo = new ArticleBodyVo();
            articleBodyVo.setContent(articleBody.getContent());
            //将得到的articlebodeyvo设置到articleVo中
            articleVo.setArticleBody(articleBodyVo);
        }
        //为true设置分类信息
        if(isCategory) {
            Integer categoryId = article.getCategoryId();
            //根据文章分类id获得 分类对象
            Category category = categoryService.findCategoryById(categoryId);
            //分类对象转换为Vo对象
            CategoryVo categoryVo = new CategoryVo();
            /*
            categoryVo.setCategoryName( category.getCategoryName());
            categoryVo.setId(category.getId());
            categoryVo.setAvatar(category.getAvatar());
             */
            BeanUtils.copyProperties(category,categoryVo);
            //将categoryvo对象设置到articleVo对象中
            articleVo.setCategory(categoryVo);
        }
        articleVo.setCreateDate(new DateTime(article.getCreateData()).toString("yyyy-MM-dd HH:mm")); //设置日期格式
        return articleVo;
    }
}
